<!-- 发布文章/封面组件 -->
<template>
  <div class="my-cover">
    <!-- 图片按钮(组件使用后上来显示的图片) -->
    <div class="btn_img" @click="openDialog()">
      <img :src="coverImageUrl" />
    </div>

    <!-- 对话框(默认不显示)
    append-to-body为true, 弹出层显示在body之上
    visible 是否显示dialog(弹出层), sync作用子组件可以修改后面变量的值
     -->
    <el-dialog
      :append-to-body="true"
      :visible.sync="dialogVisible"
      width="720px"
    >
      <!-- tab切换组件 -->
      <!-- v-model绑定的是name属性的值(默认第一个高亮) -->
      <el-tabs v-model="activeName" type="card">
        <el-tab-pane label="素材库" name="image">
          <!-- 菜单 -->
          <div style="padding-bottom: 20px">
            <el-radio-group v-model="imgType" size="mini">
              <el-radio-button label="全部"></el-radio-button>
              <el-radio-button label="收藏"></el-radio-button>
            </el-radio-group>
          </div>
          <!-- 素材列表 -->
          <!-- 分栏布局
              :gutter  栅格间隔
              class="img_item" 自己改了宽度
              :xs <768px 响应式栅格数或者栅格属性对象
              :sm ≥768px 响应式栅格数或者栅格属性对象
              :md ≥992px 响应式栅格数或者栅格属性对象
              :lg ≥1200px 响应式栅格数或者栅格属性对象
             -->
          <el-row :gutter="10" class="img_list">
            <el-col
              class="img_item"
              :xs="12"
              :sm="6"
              :md="6"
              :lg="4"
              v-for="obj in imgList"
              :key="obj.id"
              @click.native="selectedFn(obj)"
            >
              <!-- 确定图片如何适应容器框fit:cover -->
              <!-- 8个el-image都会有自己独立的obj值(v-for原因), 而且都有自己的点击事件和:class -->
              <!-- 但是selectedImgUrl变量是唯一的
                  点击哪个图片就把哪个图片的url保存到selectedImgUrl上
                  :class里的判断, 谁能对上谁就有类名
               -->
              <el-image
                style="height: 100px"
                :src="obj.url"
                fit="cover"
                :class="{ selected: selectedImgUrl === obj.url }"
              ></el-image>
            </el-col>
          </el-row>
          <!-- 分页组件 prev上一页, next下一页按钮, pager页码, total分页数 -->
          <el-pagination
            background
            layout="prev, pager, next"
            :total="total"
            @current-change="changePage"
            :current-page="reqParams.page"
          >
          </el-pagination>
        </el-tab-pane>
        <el-tab-pane label="上传图片" name="upload">
          <!-- el-upload是一个带上传网络请求功能的组件/不需要自己实现上传+axios的功能 -->
          <!-- action: 上传的地址 -->
          <!-- headers: 上传的请求头 -->
          <!-- name: 文件对应的参数(字段名)-要跟后台对应上 -->
          <!-- show-file-list展开上传的文件列表(不要) -->
          <!-- before-upload上传文件之前触发的函数 -->
          <!-- on-success-文件上传成功的触发的钩子函数 -->
          <el-upload
            class="avatar-uploader"
            action="http://api-toutiao-web.itheima.net/mp/v1_0/user/images"
            :headers="headers"
            name="image"
            :show-file-list="false"
            :before-upload="beforeAvatarUpload"
            :on-success="handleAvatarSuccess"
          >
            <img v-if="imageUrl" :src="imageUrl" class="avatar" />
            <i v-else class="el-icon-plus avatar-uploader-icon"></i>
          </el-upload>
        </el-tab-pane>
      </el-tabs>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="confirmFn">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
import defaultPng from '@/assets/default.png' // 导入图片模块对象
// 无论src里写的assets里的相对路径, 或者JS通过import引入的图片模块
// src下的统统都是模块文件(包括图片) - 运行的时候, 都会被webpack解析成一个个模块(提取数据)-放入到js中再放入到index.html中执行

// 接口
import { userImageListAPI } from '@/api'

export default {
  name: 'MyCover',
  data () {
    return {
      coverImageUrl: defaultPng, // 确认选择的图片地址
      // 控制对话框显示隐藏
      dialogVisible: false,
      // 当前tabs组件激活的选项卡的name属性的值
      activeName: 'image',
      reqParams: {
        // 请求素材库的参数对象
        collect: false, // 全局图片(true就是管后台要的收藏的)
        page: 1, // 页码
        per_page: 8 // 因为前端页面显示2行4列 (每页要8个数据)
      },
      imgList: [], // 素材图片数组
      imgType: '全部', // (默认显示全部标签页) 全部/收藏图片标签栏的文字绑定
      total: 0, // 图片总数量
      selectedImgUrl: null, // 点击选中的图片的地址
      headers: {
        Authorization: 'Bearer ' + sessionStorage.getItem('token')
      },
      imageUrl: '' // 上传成功的地址
    }
  },
  props: {
    index: Number, // 接收当前组件索引
    value: String // 接收默认图片
  },
  watch: {
    imgType (newVal) {
      // 全部和收藏文字改变
      this.reqParams.collect = !(newVal === '全部')
      this.reqParams.page = 1 // 切换后回到第一页的数据
      //   if (newVal === '全部') {
      //     this.reqParams.collect = false // 全部
      //   } else {
      //     this.reqParams.collect = true // 收藏
      //   }

      // 调用网络请求 的接口
      this.getUserImgFn()
    },
    value: {
      immediate: true, // 立即监听执行(网页刚打开时, 第一次接收值就触发函数执行)
      handler (newVal) {
        if (newVal !== undefined) {
          this.coverImageUrl = newVal
        }
      }
    }
  },
  methods: {
    beforeAvatarUpload (file) {
      // 文件上传之前 (先判断验证下)
      const isJPG = file.type === 'image/jpeg' || file.type === 'image/png'
      const isLt2M = file.size / 1024 / 1024 < 2 // 1Kb = 1024byte  (1byte=8Bit(二进制))
      // 例如 file.size的值 3000000 / 1024 / 1024的值 2.8Mb
      // 一般说的百兆指的B, 真正的网速 是b, 除以8才是真正的网速
      if (!isJPG) {
        this.$message.error('图片只能是 JPG 格式 / PNG格式!')
      }
      if (!isLt2M) {
        this.$message.error('图片大小不能超过 2Mb!')
      }

      return isJPG && isLt2M // 如果返回true就开始上传, 如果返回false则停止上传
    },
    handleAvatarSuccess (res, file) {
      // res后台返回响应结果
      // file组件内上传的文件
      // 本地预览
      // URL.createObjectURL(文件对象) 原地返回纯前端本地浏览地址 URL.createObjectURL(file.raw)

      // 问题: 上传地址还要作为封面交给ArticleAdd.vue, 所以得使用服务器上的地址才可以
      // 解决: 不能用file得用res
      this.imageUrl = res.data.url
      this.getUserImgFn() // 调用接口-让素材库也马上更新最新图片(这样马上切回来才能看到)
    },
    openDialog () {
      this.dialogVisible = true
      this.selectedImgUrl = this.coverImageUrl // 保证上一次点取消后, 本次还能自动勾选
    },
    async getUserImgFn () {
      const [err, res] = await userImageListAPI(this.reqParams)
      if (err) return
      this.imgList = res.data.data.results
      this.total = res.data.data.total_count
    },
    changePage (page) {
      // 页码改变的方法
      this.reqParams.page = page
      this.getUserImgFn()
    },
    selectedFn (obj) {
      // 点击素材的事件(选中/取消选中效果)
      // @click.native(el-col没有对click事件实现, 加了.native就让组件绑定原生的点击事件)
      // 下面逻辑: 当点击图片容器, 判断当前图片是否是已经保存的了(代表点击v的图片) - 取消选择赋予null
      // 点击selectedImgUrl没有值/跟点击的图片地址不同 - 都把最新的图片地址保存起来(间接影响页面:class)
      if (this.selectedImgUrl === obj.url) {
        this.selectedImgUrl = defaultPng // 未选中给一个默认的占位图
      } else {
        this.selectedImgUrl = obj.url
      }
    },
    confirmFn () {
      // 确定点击事件
      this.dialogVisible = false // 弹出层消失
      this.coverImageUrl = this.selectedImgUrl // 把选中的图片地址, 赋予给MyCover组件显示图片地方
      // this.coverImageUrl: 组件默认显示的图片地址
      // this.selectedImgUrl: 选中的图片地址(未选择/取消, null/defaultPng)

      // 问题: 用户选完又取消了, 对应要让ArticleAdd页面cover.images数组里的值也取消
      // 判断: 如果没选/取消了,都defaultPng, 通知外面一个false
      // this.index是当前组件的索引
      if (this.coverImageUrl === defaultPng) {
        this.$emit('coverimg', false, this.index)
      } else {
        this.$emit('coverimg', this.coverImageUrl, this.index)
      }
    }
  },
  created () {
    this.getUserImgFn()
  }
}
</script>

<style scoped lang='less'>
/* 图片按钮 */
.btn_img {
  width: 150px;
  height: 150px;
  border: 1px dashed #ddd;
  img {
    width: 100%;
    height: 100%;
    display: block;
  }
}

/* 素材列表 */
.img_list {
  margin-top: 15px;
  .img_item {
    width: 150px;
    height: 120px;
    border: 1px dashed #ddd;
    display: inline-block;
    margin-right: 15px;
    img {
      width: 100%;
      height: 100%;
      display: block;
    }
  }
}
/* 素材列表 */
.img_item {
  position: relative;
}

/* 选中样式 */
.selected::after {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.3) url(../assets/selected.png) no-repeat center /
    50px 50px;
}

// 上传图片的样式
.avatar-uploader .el-upload {
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
}
.avatar-uploader .el-upload:hover {
  border-color: #409eff;
}
.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 178px;
  height: 178px;
  line-height: 178px;
  text-align: center;
}
.avatar {
  width: 178px;
  height: 178px;
  display: block;
}
</style>
